home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / amitcptelnetf.lha / amitcp_telnet+ftp / telnet / sys_bsd.c < prev    next >
C/C++ Source or Header  |  1993-08-13  |  13KB  |  644 lines

  1. /*
  2.  * Copyright (c) 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)sys_bsd.c    5.1 (Berkeley) 9/14/90";
  22. #endif /* not lint */
  23.  
  24. /*
  25.  * The following routines try to encapsulate what is system dependent
  26.  * (at least between 4.x and dos) which is used in telnet.c.
  27.  */
  28.  
  29.  
  30. #include <fcntl.h>
  31. #include <sys/types.h>
  32. #include <sys/time.h>
  33. #include <string.h>
  34. #include <sys/socket.h>
  35. #ifdef AMI_TCP
  36. #include <bsdsocket.h>
  37. #define ioctl IoctlSocket     
  38. #else
  39. #include <ss/socket.h>
  40. #endif
  41. #include <signal.h>
  42. #include <errno.h>
  43. #include <arpa/telnet.h>
  44. #ifdef __SASC
  45. #include <ios1.h>
  46. #endif
  47. #include "ring.h"
  48.  
  49. #include "fdset.h"
  50.  
  51. #include "defines.h"
  52. #include "externs.h"
  53. #include "types.h"
  54.  
  55. #define    SIG_FUNC_RET    int
  56.  
  57. int
  58.     tout,            /* Output file descriptor */
  59.     tin,            /* Input file descriptor */
  60.     net;
  61.  
  62. #ifndef AMI_TCP
  63. struct    tchars otc = { 0 }, ntc = { 0 };
  64. struct    sgttyb ottyb = { 0 }, nttyb = { 0 };
  65. #endif
  66. int    olmode = 0;
  67. # define cfgetispeed(ptr)    (ptr)->sg_ispeed
  68. # define cfgetospeed(ptr)    (ptr)->sg_ospeed
  69. # define old_tc ottyb
  70.  
  71. static fd_set ibits, obits, xbits;
  72.  
  73. //void (*signal())()
  74. //{    return;
  75. //}
  76.  
  77. init_sys()
  78. {
  79.     tout = fileno(stdout);
  80.     tin = fileno(stdin);
  81.     FD_ZERO(&ibits);
  82.     FD_ZERO(&obits);
  83.     FD_ZERO(&xbits);
  84.  
  85.     errno = 0;
  86. }
  87.  
  88.  
  89. TerminalWrite(buf, n)
  90. char    *buf;
  91. int    n;
  92. {
  93.     return write(tout, buf, n);
  94. }
  95.  
  96. TerminalRead(buf, n)
  97. char    *buf;
  98. int    n;
  99. {
  100.     return read(tin, buf, n);
  101. }
  102.  
  103. /*
  104.  *
  105.  */
  106.  
  107. int
  108. TerminalAutoFlush()
  109. {
  110.     return 1;
  111. }
  112.  
  113.  
  114. /*
  115.  * Flush output to the terminal
  116.  */
  117.  
  118. void
  119. TerminalFlushOutput()
  120. {
  121.     fflush(stdout);
  122. }
  123.  
  124. void
  125. TerminalSaveState()
  126. {
  127. return;
  128. }
  129.  
  130. cc_t *
  131. tcval(func)
  132. register int func;
  133. {
  134.     switch(func) {
  135.     case SLC_SYNCH:
  136.     case SLC_BRK:
  137.     case SLC_EOR:
  138.     default:
  139.     return((cc_t *)0);
  140.     }
  141. }
  142.  
  143. void
  144. TerminalDefaultChars()
  145. {
  146. return;
  147. }
  148.  
  149. #ifdef notdef
  150. void
  151. TerminalRestoreState()
  152. {
  153. }
  154. #endif
  155.  
  156. /*
  157.  * TerminalNewMode - set up terminal to a specific mode.
  158.  *    MODE_ECHO: do local terminal echo
  159.  *    MODE_FLOW: do local flow control
  160.  *    MODE_TRAPSIG: do local mapping to TELNET IAC sequences
  161.  *    MODE_EDIT: do local line editing
  162.  *
  163.  *    Command mode:
  164.  *        MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
  165.  *        local echo
  166.  *        local editing
  167.  *        local xon/xoff
  168.  *        local signal mapping
  169.  *
  170.  *    Linemode:
  171.  *        local/no editing
  172.  *    Both Linemode and Single Character mode:
  173.  *        local/remote echo
  174.  *        local/no xon/xoff
  175.  *        local/no signal mapping
  176.  */
  177.  
  178.  
  179. void
  180. TerminalNewMode(f)
  181. register int f;
  182. {
  183.     static int prevmode = 0;
  184. #ifndef    USE_TERMIO
  185. #ifdef __SASC
  186.      int    ami_cbreak = 0;
  187. #else
  188.     struct sgttyb sb;
  189. #endif
  190. #endif
  191.     int lmode;
  192.     int onoff;
  193.     int old;
  194.  
  195.     globalmode = f&~MODE_FORCE;
  196.     if (prevmode == f)
  197.     return;
  198.  
  199.     /*
  200.      * Write any outstanding data before switching modes
  201.      * ttyflush() returns 0 only when there is no more data
  202.      * left to write out, it returns -1 if it couldn't do
  203.      * anything at all, otherwise it returns 1 + the number
  204.      * of characters left to write.
  205. #ifndef    USE_TERMIO
  206.      * We would really like ask the kernel to wait for the output
  207.      * to drain, like we can do with the TCSADRAIN, but we don't have
  208.      * that option.  The only ioctl that waits for the output to
  209.      * drain, TIOCSETP, also flushes the input queue, which is NOT
  210.      * what we want (TIOCSETP is like TCSADFLUSH).
  211. #endif
  212.      */
  213.     old = ttyflush(SYNCHing|flushout);
  214.     if (old < 0 || old > 1) {
  215.     do {
  216.         /*
  217.          * Wait for data to drain, then flush again.
  218.          */
  219.         old = ttyflush(SYNCHing|flushout);
  220.     } while (old < 0 || old > 1);
  221.     }
  222.  
  223.     old = prevmode;
  224.     prevmode = f&~MODE_FORCE;
  225.     lmode = olmode;
  226.  
  227.     if (f&MODE_ECHO) {
  228. #ifndef __SASC
  229.     sb.sg_flags |= ECHO;
  230. #endif
  231.     } else {
  232. #ifndef __SASC
  233.     sb.sg_flags &= ~ECHO;
  234. #endif
  235.     }
  236.  
  237.     if ((f&MODE_FLOW) == 0) {
  238.     }
  239.  
  240.     if ((f&MODE_TRAPSIG) == 0) {
  241.     localchars = 0;
  242.     } else {
  243.     localchars = 1;
  244.     }
  245.  
  246.     if (f&MODE_EDIT) {
  247. #ifdef __SASC
  248.     ami_cbreak = 0;
  249. #else
  250.     sb.sg_flags &= ~CBREAK;
  251.     sb.sg_flags &= ~RAW;
  252.     sb.sg_flags |= CRMOD;
  253. #endif
  254.     } else {
  255. #ifdef __SASC
  256.     ami_cbreak = 1;
  257. #else
  258.     sb.sg_flags |= CBREAK;
  259.     sb.sg_flags |= RAW;
  260.     if (f&MODE_ECHO)
  261.         sb.sg_flags |= CRMOD;
  262.     else
  263.         sb.sg_flags &= ~CRMOD;
  264. #endif
  265.     }
  266.  
  267.     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
  268.     }
  269.  
  270.     if (f&MODE_SOFT_TAB) {
  271. #ifndef __SASC
  272.     sb.sg_flags |= XTABS;
  273. #endif
  274.     } else {
  275. #ifndef __SASC
  276.     sb.sg_flags &= ~XTABS;
  277. #endif
  278.     }
  279.  
  280.     if (f&MODE_LIT_ECHO) {
  281.     } else {
  282.     }
  283.  
  284.     if (f == -1) {
  285.     onoff = 0;
  286.     } else {
  287.     onoff = 1;
  288.     }
  289.  
  290.     if (f != -1) {
  291.     /*
  292.      * We don't want to process ^Y here.  It's just another
  293.      * character that we'll pass on to the back end.  It has
  294.      * to process it because it will be processed when the
  295.      * user attempts to read it, not when we send it.
  296.      */
  297.     } else {
  298.     lmode = olmode;
  299.     }
  300. #ifdef __SASC
  301.     SetMode(chkufb(0)->ufbfh,ami_cbreak);
  302. #else
  303.     SetMode(_devtab[0].fd,(sb.sg_flags & CBREAK) ? 1L : 0L);
  304. #endif
  305.  
  306.     ioctl(tin, FIONBIO, (char *)&onoff);
  307.     ioctl(tout, FIONBIO, (char *)&onoff);
  308. }
  309.  
  310.  
  311. int
  312. TerminalWindowSize(rows, cols)
  313. long *rows, *cols;
  314. {
  315.     return 0;
  316. }
  317.  
  318. int
  319. NetClose(fd)
  320. int    fd;
  321. {
  322. #ifdef AMI_TCP
  323.      return CloseSocket(fd);
  324. #else
  325.     return s_close(fd);
  326. #endif
  327. }
  328.  
  329.  
  330. void
  331. NetNonblockingIO(fd, onoff)
  332. int
  333.     fd,
  334.     onoff;
  335. {
  336.     ioctl(fd, FIONBIO, (char *)&onoff);
  337. }
  338.  
  339. /*
  340.  * Various signal handling routines.
  341.  */
  342.  
  343. /* ARGSUSED */
  344. static SIG_FUNC_RET
  345. deadpeer(sig)
  346. int sig;
  347. {
  348.     setcommandmode();
  349.     longjmp(peerdied, -1);
  350. }
  351.  
  352. /* ARGSUSED */
  353. static SIG_FUNC_RET
  354. intr(sig)
  355. int sig;
  356. {
  357.     if (localchars) {
  358.     intp();
  359.     return;
  360.     }
  361.     setcommandmode();
  362.     longjmp(toplevel, -1);
  363. }
  364.  
  365. /* ARGSUSED */
  366. static SIG_FUNC_RET
  367. intr2(sig)
  368. int sig;
  369. {
  370.     if (localchars) {
  371.         sendabort();
  372.     return;
  373.     }
  374. }
  375.  
  376. #ifdef    SIGTSTP
  377. /* ARGSUSED */
  378. static SIG_FUNC_RET
  379. susp(sig)
  380. int sig;
  381. {
  382.     if (localchars)
  383.     sendsusp();
  384. }
  385. #endif
  386.  
  387. #ifdef    SIGWINCH
  388. /* ARGSUSED */
  389. static SIG_FUNC_RET
  390. sendwin(sig)
  391. int sig;
  392. {
  393.     if (connected) {
  394.     sendnaws();
  395.     }
  396. }
  397. #endif
  398.  
  399. #ifdef    SIGINFO
  400. /* ARGSUSED */
  401. static SIG_FUNC_RET
  402. ayt(sig)
  403. int sig;
  404. {
  405.     if (connected)
  406.     sendayt();
  407.     else
  408.     ayt_status();
  409. }
  410. #endif
  411.  
  412. void
  413. sys_telnet_init()
  414. {
  415.     setconnmode(0);
  416.  
  417.     NetNonblockingIO(net, 1);
  418.  
  419. #if    defined(SO_OOBINLINE)
  420.    {    int one=1;
  421. #ifdef AMI_TCP
  422.     if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one,sizeof(one)) == -1) 
  423. #else
  424.     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, &one,sizeof(one)) == -1) 
  425. #endif
  426.     {
  427.         perror("SetSockOpt");
  428.     }
  429.    }
  430. #endif    /* defined(SO_OOBINLINE) */
  431. }
  432.  
  433. /*
  434.  * Process rings -
  435.  *
  436.  *    This routine tries to fill up/empty our various rings.
  437.  *
  438.  *    The parameter specifies whether this is a poll operation,
  439.  *    or a block-until-something-happens operation.
  440.  *
  441.  *    The return value is 1 if something happened, 0 if not.
  442.  */
  443.  
  444. int
  445. process_rings(netin, netout, netex, ttyin, ttyout, poll)
  446. int poll;        /* If 0, then block until something to do */
  447. {
  448.     register int c;
  449.         /* One wants to be a bit careful about setting returnValue
  450.          * to one, since a one implies we did some useful work,
  451.          * and therefore probably won't be called to block next
  452.          * time (TN3270 mode only).
  453.          */
  454.     int returnValue = 0;
  455.     static struct timeval TimeValue = { 0 };
  456.     static struct timeval Quickie = {0L,20000L};
  457.     extern long bytesin;
  458.     if (netout) {
  459.     FD_SET(net, &obits);
  460.     } 
  461.     if (netin) {
  462.     FD_SET(net, &ibits);
  463.     }
  464.     if (netex) {
  465.     FD_SET(net, &xbits);
  466.     }
  467.     if ((c = select(16, &ibits, &obits, &xbits,
  468.             (poll == 0)? (struct timeval *)&Quickie : &TimeValue)) < 0) {
  469.     if (c == -1) {
  470.             /*
  471.              * we can get EINTR if we are in line mode,
  472.              * and the user does an escape (TSTP), or
  473.              * some other signal generator.
  474.              */
  475.         if (errno == EINTR) {
  476.         return 0;
  477.         }
  478.             /* I don't like this, does it ever happen? */
  479.         printf("sleep(5) from telnet, after select\r\n");
  480.         sleep(5);
  481.     }
  482.     return 0;
  483.     }
  484.  
  485.     /*
  486.      * Any urgent data?
  487.      */
  488.     if (FD_ISSET(net, &xbits)) {
  489.     FD_CLR(net, &xbits);
  490.     SYNCHing = 1;
  491.     (void) ttyflush(1);    /* flush already enqueued data */
  492.     }
  493.  
  494.     /*
  495.      * Something to read from the network...
  496.      */
  497.     if (FD_ISSET(net, &ibits)) {
  498.     int canread;
  499.  
  500.     FD_CLR(net, &ibits);
  501.     canread = ring_empty_consecutive(&netiring);
  502. #if    !defined(SO_OOBINLINE)
  503.         /*
  504.          * In 4.2 (and some early 4.3) systems, the
  505.          * OOB indication and data handling in the kernel
  506.          * is such that if two separate TCP Urgent requests
  507.          * come in, one byte of TCP data will be overlaid.
  508.          * This is fatal for Telnet, but we try to live
  509.          * with it.
  510.          *
  511.          * In addition, in 4.2 (and...), a special protocol
  512.          * is needed to pick up the TCP Urgent data in
  513.          * the correct sequence.
  514.          *
  515.          * What we do is:  if we think we are in urgent
  516.          * mode, we look to see if we are "at the mark".
  517.          * If we are, we do an OOB receive.  If we run
  518.          * this twice, we will do the OOB receive twice,
  519.          * but the second will fail, since the second
  520.          * time we were "at the mark", but there wasn't
  521.          * any data there (the kernel doesn't reset
  522.          * "at the mark" until we do a normal read).
  523.          * Once we've read the OOB data, we go ahead
  524.          * and do normal reads.
  525.          *
  526.          * There is also another problem, which is that
  527.          * since the OOB byte we read doesn't put us
  528.          * out of OOB state, and since that byte is most
  529.          * likely the TELNET DM (data mark), we would
  530.          * stay in the TELNET SYNCH (SYNCHing) state.
  531.          * So, clocks to the rescue.  If we've "just"
  532.          * received a DM, then we test for the
  533.          * presence of OOB data when the receive OOB
  534.          * fails (and AFTER we did the normal mode read
  535.          * to clear "at the mark").
  536.          */
  537.     if (SYNCHing) {
  538.         int atmark;
  539.         static int bogus_oob = 0, first = 1;
  540.  
  541.         s_ioctl(net, SIOCATMARK, (char *)&atmark);
  542.         if (atmark) {
  543.         c = recv(net, netiring.supply, canread, MSG_OOB);
  544.         if ((c == -1) && (errno == EINVAL)) {
  545.             c = recv(net, netiring.supply, canread, 0);
  546.             if (clocks.didnetreceive < clocks.gotDM) {
  547.             SYNCHing = stilloob(net);
  548.             }
  549.         } else if (first && c > 0) {
  550.             /*
  551.              * Bogosity check.  Systems based on 4.2BSD
  552.              * do not return an error if you do a second
  553.              * recv(MSG_OOB).  So, we do one.  If it
  554.              * succeeds and returns exactly the same
  555.              * data, then assume that we are running
  556.              * on a broken system and set the bogus_oob
  557.              * flag.  (If the data was different, then
  558.              * we probably got some valid new data, so
  559.              * increment the count...)
  560.              */
  561.             int i;
  562.             i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
  563.             if (i == c &&
  564.               bcmp(netiring.supply, netiring.supply + c, i) == 0) {
  565.             bogus_oob = 1;
  566.             first = 0;
  567.             } else if (i < 0) {
  568.             bogus_oob = 0;
  569.             first = 0;
  570.             } else
  571.             c += i;
  572.         }
  573.         if (bogus_oob && c > 0) {
  574.             int i;
  575.             /*
  576.              * Bogosity.  We have to do the read
  577.              * to clear the atmark to get out of
  578.              * an infinate loop.
  579.              */
  580.             i = read(net, netiring.supply + c, canread - c);
  581.             if (i > 0)
  582.             c += i;
  583.         }
  584.         } else {
  585.         c = recv(net, netiring.supply, canread, 0);
  586.         }
  587.     } else {
  588.         c = recv(net, netiring.supply, canread, 0);
  589.     }
  590.     settimer(didnetreceive);
  591. #else    /* !defined(SO_OOBINLINE) */
  592.     c = recv(net, netiring.supply, canread, 0);
  593. #endif    /* !defined(SO_OOBINLINE) */
  594.     if (c < 0 && errno == EWOULDBLOCK) {
  595.         c = 0;
  596.     } else if (c <= 0) {
  597.         return -1;
  598.     }
  599.     if (netdata) {
  600.         Dump('<', netiring.supply, c);
  601.     }
  602.     if (c)
  603.         bytesin+=c;
  604.         ring_supplied(&netiring, c);
  605.     returnValue = 1;
  606.     }
  607.  
  608.     /*
  609.      * Something to read from the tty...
  610.      */
  611. #ifdef __SASC
  612.     if (WaitForChar(chkufb(0)->ufbfh,Quickie.tv_usec)) {
  613. #else
  614.     if (WaitForChar(_devtab[0].fd,Quickie.tv_usec)) {
  615. #endif
  616. //    FD_CLR(tin, &ibits);
  617.     c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
  618.     if (c < 0 && errno == EWOULDBLOCK) {
  619.         c = 0;
  620.     } else {
  621.         /* EOF detection for line mode!!!! */
  622.         if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
  623.             /* must be an EOF... */
  624. #ifndef __SASC
  625.         *ttyiring.supply = termEofChar;
  626. #endif
  627.         c = 1;
  628.         }
  629.         if (c <= 0) {
  630.         return -1;
  631.         }
  632.         ring_supplied(&ttyiring, c);
  633.     }
  634.     returnValue = 1;        /* did something useful */
  635.     }
  636.  
  637.     if (FD_ISSET(net, &obits)) {
  638.     FD_CLR(net, &obits);
  639.     returnValue |= netflush();
  640.     }
  641.     returnValue |= (ttyflush(SYNCHing|flushout) > 0);
  642.     return returnValue;
  643. }
  644.